6.4.1 设置数据库

在正式开始之前,我们需要再次对数据库进行设置,不过跟上次只创建一个表的做法不同,这一次我们将会创建两个表。此外,这次设置需要用到的命令跟上一次设置使用的命令完全一样,只是被执行的 setup.sql 脚本跟之前的有所不同,代码清单6-13展示了新脚本的具体定义。

代码清单6-13 创建两个相关联的表

drop table posts cascade if exists;
drop table comments if exists;
create table posts (
 id   serial primary key,
 content text,
 author varchar(255)
);
create table comments (
 id   serial primary key,
 content text,
 author varchar(255),
 post_id integer references posts(id)
);

这次的脚本除了会创建 posts 表之外,还会创建 comments 表, comments 表的大部分列都跟 posts 表一样,主要区别在于 comments 表多了一个额外的 post_id 列:这个 post_id 会作为外键(foreign key),对 posts 表的主键 id 进行引用。此外,因为 posts 表和 comments 表现在已经通过主键和外键建立起了关联,所以用户在删除 posts 表的同时也需要将 comments 表一并删除;否则,由于 comments 表对 posts 表的依赖关系,删除 posts 表这一操作将无法正常执行。

设置好相应的数据库表之后,现在让我们来看看如何使用Go语言实现一对多以及多对一关系。代码清单6-14展示了具体的实现代码,这些代码都存储在一个名为 store.go 的文件里面。

代码清单6-14 使用Go语言实现一对多以及多对一关系

package main
import (
  "database/sql"
  "errors"
  "fmt"
  _ "github.com/lib/pq"
)
type Post struct {
  Id   int
  Content string
  Author string
 Comments []Comment
}
type Comment struct {
  Id   int
  Content string
  Author string
  Post  *Post
}
var Db *sql.DB
func init() {
  var err error
  Db, err = sql.Open("postgres", "user=gwp dbname=gwp password=gwp
  ➥sslmode=disable")
  if err != nil {
    panic(err)
  }
}
func (comment *Comment) Create() (err error) { ❶
  if comment.Post == nil {
    err = errors.New("Post not found")
    return
  }
  err = Db.QueryRow("insert into comments (content, author, post_id)
  ➥values ($1, $2, $3) returning id", comment.Content, comment.Author,
  ➥comment.Post.Id).Scan(&comment.Id)
  return
}
func GetPost(id int) (post Post, err error) {
  post = Post{}
   post.Comments = []Comment{}
  err = Db.QueryRow("select id, content, author from posts where id =
  ➥$1", id).Scan(&post.Id, &post.Content, &post.Author)
  rows, err := Db.Query("select id, content, author from comments")
  if err != nil {
    return
  }
  for rows.Next() {
    comment := Comment{Post: &post}
    err = rows.Scan(&comment.Id, &comment.Content, &comment.Author)
    if err != nil {
      return
    }
    post.Comments = append(post.Comments, comment)
  }
  rows.Close()
  return
}
func (post *Post) Create() (err error) {
  err = Db.QueryRow("insert into posts (content, author) values ($1, $2)
  ➥returning id", post.Content, post.Author).Scan(&post.Id)
  return
}
func main() {
  post := Post{Content: "Hello World!", Author: "Sau Sheong"}
  post.Create()
  comment := Comment{Content: "Good post!", Author: "Joe", Post: &post}
  comment.Create()
  readPost, _ := GetPost(post.Id) ❷
 fmt.Println(readPost)
fmt.Println(readPost.Comments)  ❸
fmt.Println(readPost.Comments[0].Post)}

❶ 创建一条评论

❷ {1 Hello World! Sau Sheong [{1 Good post! Joe 0xc20802a1c0}]}

❸ [{1 Goodpost! Joe0xc20802a1c0}

❹ &{1 Hello World! Sau Sheong [{1 Good post! Joe 0xc20802a1c0}]}

results matching ""

    No results matching ""